#include "KcPickSameFile.h"
#include <QCryptographicHash>
#include <QFileInfo>


namespace kPrivate
{
    QByteArray* readFile(const QString& filePath)
    {
        QFile file(filePath);
        if(!file.open(QIODevice::ReadOnly))
            return nullptr;

        auto ba = new QByteArray(file.size(), Qt::Uninitialized);
        file.read(ba->data(), ba->size()); // TODO: 判断是否读取成功
        return ba;
    }

    QByteArray calcMD5(const QByteArray& ba)
    {
        QCryptographicHash ch(QCryptographicHash::Md5);
        ch.addData(ba);
        auto fsize = ba.size();
        return ch.result().append(QByteArray::fromRawData((char*)&fsize, sizeof(fsize)));
    }
}


bool KcPickSameFile::doPick_(const QString& filePath)
{
    auto fsize = QFileInfo(filePath).size();
    if (!size2Files_.contains(fsize)) {
        size2Files_.insert(fsize, filePath);
        return false; // 当前尺寸只有1个文件，先挂起，不执行读取操作
    }

    return true;
}


void* KcPickSameFile::doRead_(const QString& filePath)
{
    auto fsize = QFileInfo(filePath).size();
    Q_ASSERT(size2Files_.contains(fsize));

    auto& firstFile = size2Files_[fsize];
    if (!firstFile.isEmpty()) { // 读取挂起的文件
        emit fileRead(firstFile, kPrivate::readFile(firstFile)); // 补发fileRead信号
        firstFile.clear(); // 清空文件路径，表示挂起文件已读取
    }

    return kPrivate::readFile(filePath);
}

void KcPickSameFile::doCalc_(const QString& filePath, void* fileObj)
{
    auto ba = (QByteArray*)(fileObj);
    if (ba->size() > 0) { // 忽略空文件
        auto& pos = result_[kPrivate::calcMD5(*ba)];
        pos.first.append(filePath);
        if (pos.first.size() == 1) {
            pos.second = -1;
            return;
        }
        else if (pos.first.size() == 2) {
            pos.second = groupId_++;
            emit resultFound(pos.second, pos.first.front()); // 补发一个信号
        }

        emit resultFound(pos.second, filePath);
    }
}


void KcPickSameFile::dropFileObject_(void* fileObj)
{
    delete (QByteArray*)(fileObj);
}


